package com.ruoyi.common.utils.jsch;

import com.jcraft.jsch.*;
import com.ruoyi.common.exception.ServiceException;

import java.io.ByteArrayOutputStream;
import java.io.File;
import java.io.IOException;
import java.io.InputStream;
import java.nio.charset.Charset;

public class JschUtil {

    public static final int timeout = 5000;
    public static final String COMMAND_SYS_INFO = "bash -c hostname && arch && uname -a|awk '{print $3 }' && ip addr show | grep -v inet6 | grep _IP_|awk '{print $NF}'|head -1";//
    public static final String COMMAND_CHECK_PORT_USED = "netstat -tln | grep :";
    public static boolean testConnect(JschAuth auth){
        Session session = null;
        try {
            session = getSession(auth);
        }finally {
            if(session!=null)
                session.disconnect();
        }
        return true;
    }

    public static Session getSession(JschAuth auth){
        // 创建一个新的JSch对象
        JSch jsch = new JSch();
        Session session = null;
        try {
            session = jsch.getSession(auth.getUsername(),auth.getIp(),auth.getPort());
            session.setPassword(auth.getPassword());
            session.setConfig("StrictHostKeyChecking","no");
            session.setTimeout(timeout);
            session.connect();
        } catch (JSchException e) {
            e.printStackTrace();
            throw new ServiceException("创建ssh连接失败："+e.getMessage());
        }
        return session;
    }

    public static JschResult execShell(JschAuth auth,String command) throws Exception {
        Session session = null;
        Channel channel = null;
        try {
            command = command.replaceAll("_IP_",auth.getIp());
            session = getSession(auth);
            channel = session.openChannel("exec");
            ((ChannelExec) channel).setCommand(command);
            channel.setInputStream(null); // 禁用 I/O 流输出
            ByteArrayOutputStream errorStream = new ByteArrayOutputStream();
            ((ChannelExec) channel).setErrStream(errorStream); // 把错误信息输出到系统的错误输出流中
            InputStream in = channel.getInputStream();
            channel.connect();
            while (!channel.isClosed()){
                Thread.sleep(1000);
            }
            int exitStatus = channel.getExitStatus();
            if(exitStatus!=0){
               return JschResult.build(exitStatus,errorStream.toString());
            }

            byte[] buffer = new byte[1024];
            int numRead;
            StringBuffer result = new StringBuffer();
            while((numRead=in.read(buffer))>0){
                result.append(new String(buffer, 0, numRead));
            }
            return JschResult.build(exitStatus,result.toString());
        } finally{
            if(channel!=null)
                channel.disconnect();
            if(session!=null)
                session.disconnect();
        }
    }

    /**
     * scp上传软件包
     * @param auth 连接认证信息
     * @param localFilePath 本地文件路径
     * @param remoteFilePath  上传文件路径
     * @return
     */
    public static JschResult scpPackage(JschAuth auth,String localFilePath,String remoteFilePath) {
        Session session = null;
        ChannelSftp  channel = null;
        try {
            session = getSession(auth);
            // 打开 SFTP 通道
            channel = (ChannelSftp) session.openChannel("sftp");
            channel.connect();
            // 上传文件
            File localFile = new File(localFilePath);
            channel.put(localFile.getAbsolutePath(), remoteFilePath);
            return JschResult.build(0,"");
        } catch (JSchException | SftpException e){
            throw new ServiceException(e.getMessage());
        } finally{
            if(channel!=null)
                channel.disconnect();
            if(session!=null)
                session.disconnect();
        }
    }
}
